package com.gitee.lougnib.simplekits.common_impls.velocity2;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;

import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;

import com.gitee.lougnib.simplekits.common_faces.exception.Exceptions;
import com.gitee.lougnib.simplekits.common_faces.template.TemplateService;

public class Velocity2TemplateService implements TemplateService {

    /**
     * 模板引擎。
     */
    private VelocityEngine velocityEngine = null;

    /**
     * 设置模板引擎。
     * @param velocityEngine 模板引擎
     */
    public void setVelocityEngine(VelocityEngine velocityEngine) {
        this.velocityEngine = velocityEngine;
    }

    /**
     * 合并模板。
     *
     * @param templateName 模板名
     * @param context 上下文内容
     * @return 合并后的字符串
     */
    public String merge(String templateName, Map<String, Object> context) {
        try (Writer writer = new StringWriter()) {

            Template tmp = getVelocityEngine().getTemplate(templateName);
            tmp.merge(Velocity2Kit.createContext(context), writer);

            writer.flush();

            return writer.toString();
        } catch (IOException e) {
            throw Exceptions.toRuntime(e, "合并模板失败。");
        }
    }

    /**
     * 合并模板，并输出到文件。输出的字符集是 UTF-8。
     *
     * @param templateName 模板名
     * @param context 上下文内容
     * @param filePath 输出路径
     */
    public void merge(String templateName, Map<String, Object> context, String filePath) {
        merge(templateName, context, new File(filePath), "UTF-8");
    }

    /**
     * 合并模板，并输出到文件。输出的字符集是 UTF-8。
     *
     * @param templateName 模板名
     * @param context 上下文内容
     * @param encoding 输出的字符集
     * @param filePath 输出路径
     */
    public void merge(String templateName, Map<String, Object> context, String filePath, String encoding) {
        merge(templateName, context, new File(filePath), encoding);
    }

    /**
     * 合并模板，并输出到文件。输出的字符集是 UTF-8。
     *
     * @param templateName 模板名
     * @param context 上下文内容
     * @param outputFile 输出路径
     */
    public void merge(String templateName, Map<String, Object> context, File outputFile) {
        merge(templateName, context, outputFile, "UTF-8");
    }


    /**
     * 合并模板，并输出到文件。输出的字符集是 UTF-8。
     *
     * @param templateName 模板名
     * @param context 上下文内容
     * @param outputFile 输出路径
     * @param encoding 输出的字符集
     */
    public void merge(String templateName, Map<String, Object> context, File outputFile, String encoding) {
        if (outputFile.getParentFile() != null && !outputFile.getParentFile().exists()) {
            outputFile.getParentFile().mkdirs();
        }

        try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), encoding))) {

            Template tmp = getVelocityEngine().getTemplate(templateName);
            tmp.merge(Velocity2Kit.createContext(context), writer);

            writer.flush();
        } catch (IOException e) {
        	throw Exceptions.toRuntime(e, "合并模板失败。");
        }
    }

    /**
     * 合并模板，并输出到文件。输出的字符集是 UTF-8。
     *
     * @param templateName 模板名
     * @param context 上下文内容
     * @param out 输出流
     * @param encoding 输出的字符集
     */
    public void merge(String templateName, Map<String, Object> context, OutputStream out, String encoding) {
        try (Writer writer = new BufferedWriter(new OutputStreamWriter(out, encoding))) {

            Template tmp = getVelocityEngine().getTemplate(templateName);
            tmp.merge(Velocity2Kit.createContext(context), writer);

            writer.flush();
        } catch (IOException e) {
        	throw Exceptions.toRuntime(e, "合并模板失败。");
        }
    }

    /**
     * 取得模板引擎。
     *
     * @return 模板引擎
     */
    private VelocityEngine getVelocityEngine() {
        if (this.velocityEngine == null) {
            // 默认初始化一个类路径资源载入的模板引擎
            this.velocityEngine = Velocity2Kit.getClasspathVelocityEngine();
        }

        return this.velocityEngine;
    }
}
